package com.blacksea.resourceserver.web.security;

import com.blacksea.resourceserver.web.security.filter.TokenAuthFilter;
import com.blacksea.resourceserver.web.security.login.UnAuthenticationEntryPoint;
import com.blacksea.resourceserver.web.security.logout.TokenLogoutHandler;
import com.blacksea.resourceserver.web.security.token.TokenManager;

import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Configuration;
import org.springframework.security.config.annotation.web.builders.HttpSecurity;
import org.springframework.security.config.annotation.web.configuration.EnableWebSecurity;
import org.springframework.security.config.annotation.web.configuration.WebSecurityConfigurerAdapter;
import org.springframework.security.web.authentication.www.BasicAuthenticationFilter;

/**
 * Spring security配置类
 * <p>
 * 自定义
 * 配套Bean: CusUsernamePasswordAuthenticationProvider
 * 配套Bean: AuthenticationLoginFailedEventListener
 * 配套Bean: AuthenticationLoginSucceededEventListener
 *
 * @author blacksea3(jxt) 2021/2/6 15:55
 */
@Configuration
@EnableWebSecurity(debug = true)
public class SecurityConfig extends WebSecurityConfigurerAdapter {

    // httpBasic提供无权限处理入口, BasicAuthenticationFilter
    @Autowired
    private UnAuthenticationEntryPoint unAuthenticationEntryPoint;

    // 提交登录url, 资源服务器已弃用登录url
    //@Value("${custom_doLoginUrl}")
    //private String doLoginUrl;

    // 提交注销url
    @Value("${custom_doLogoutUrl}")
    private String doLogoutUrl;

    // 自定义TokenAuthFilter和自定义TokenLoginFilter 需要使用的Token处理类
    @Autowired
    private TokenManager tokenManager;

    // 自定义需要使用的TokenAuthFilter请求token头标识
    @Value("${custom_securityRequestHeaderToken}")
    private String reqHeaderToken;

    // 自定义登出handler
    @Autowired
    private TokenLogoutHandler tokenLogoutHandler;

    /**
     * Spring security 主配置:
     *
     * @param http .
     * @throws Exception .
     */
    @Override
    protected void configure(HttpSecurity http) throws Exception {
        http
            //允许跨域, Spring Boot + Spring Security项目必须和CrossConfig配置类同时使用
            .cors()
            .and()
            // 禁用CSRF
            .csrf()
            .disable()

            // URL权限配置
            .authorizeRequests()
            .antMatchers("/**")
            // .antMatchers("/blog/**", "/article/**")
            .permitAll()
            .and()
            .authorizeRequests()
            .anyRequest()
            .authenticated()

            // formLogin 认证方式, 登录配置
            // .and()
            // .formLogin()
            // .loginProcessingUrl(doLoginUrl) //此url请给一个controller, 或注释掉此行用默认的
            // .loginPage(loginRedirectUrl)
            // .usernameParameter(loginUsernameParameter)
            // .passwordParameter(loginPasswordParameter)

            // 注销配置
            .and()
            .logout()
            .logoutUrl(doLogoutUrl)
            .logoutSuccessHandler(tokenLogoutHandler)
            .permitAll()

            .and()
            .httpBasic()
            // 对于httpBasic 仅有 BasicAuthenticationFilter
            // BasicAuthenticationFilter中的匿名用户无权限处理
            // .authenticationEntryPoint(unAuthenticationEntryPoint)
            .and()
            // 自定义过滤器: 加在BasicAuthenticationFilter之前, 不使用BasicAuthenticationFilter的认证和授权逻辑
            // 先授权认证再登录认证
            // .addFilterBefore(new TokenLoginFilter(authenticationManager(), this.tokenManager, doLoginUrl),
            //        BasicAuthenticationFilter.class)    //设置自定义用户名密码认证 过滤器, 不使用, 因为认证交给认证服务器
            .addFilterBefore(new TokenAuthFilter(authenticationManager(), this.tokenManager, this.reqHeaderToken,
                    unAuthenticationEntryPoint
                ),
                BasicAuthenticationFilter.class)    // 设置自定义授权处理 过滤器
        ;
    }
}
